<script lang="ts" setup>
import { Form, Input, Select, TabPane, Tooltip, Button, Drawer, Textarea, message, Switch, InputNumber, Row, Col } from 'ant-design-vue'
import {
  type IApiCaseStep,
  type IApiCaseStepAssertion,
  type IApiCaseStepRelation,
  type IApiConstantSelectOptions,
  defaultWithIApiCaseStepAssertion,
  defaultWithIApiCaseStepRelation,
} from '../../types/apis/api-case'
import {
  type IDatabaseStepAssertion,
  type IDatabaseConstantSelectOptions,
  defaultWithIDatabaseStepAssertion
} from '../../types/apis/database_msg'
import type RequestConfigVue from './RequestConfig.vue'
import type { ComponentExposed } from 'vue-component-type-helpers'
import { ref, reactive, watch, nextTick } from 'vue';
import type { DrawerProps } from 'ant-design-vue';
import type { AfterFetchContext } from '@vueuse/core'
import type { IBasic } from '../../types/apis/basic'
import { objectSerializer, objectDeserializer } from '../../utils/internal'
import type { ColumnsType } from 'ant-design-vue/es/table'
import type { IDatabase } from '../../types/apis/database_msg';
import { useCustomFetch } from '../../composables/custom-fetch'


defineProps<{
  databaseConstantSelectOptions: IDatabaseConstantSelectOptions,
  apiConstantSelectOptions: IApiConstantSelectOptions
}>()
const selectedStep = defineModel<IApiCaseStep>('selectedStep', {
  required: true,
})

const globalConfig = useGlobalConfigStore()
const requestConfigRef = ref<ComponentExposed<typeof RequestConfigVue>>()

const columnsWithAssertion: ColumnsType<any> = [
  { title: '断言方式', dataIndex: 'mode', key: 'mode' },
  { title: '断言动作', dataIndex: 'action', key: 'action' },
  { title: '字段名', dataIndex: 'field', key: 'field' },
  { title: '预期值', dataIndex: 'value', key: 'value' },
  { title: '操作', dataIndex: 'operator', key: 'operator', width: 200 },
]
const dataSourceWithAssertion = ref<IDatabaseStepAssertion[]>([])
const dataSourceWithRelation = ref<IApiCaseStepRelation[]>([])

async function deserialize() {
  await nextTick()
  dataSourceWithAssertion.value = objectDeserializer(
    selectedStep.value.assertion,
    true,
  )

}

function serialize() {
  selectedStep.value.assertion = objectSerializer(dataSourceWithAssertion.value)
}

watch(
  selectedStep,
  async () => {
    await deserialize()
  },
  { deep: true, immediate: true },
)


defineExpose({ serialize })


const databaseId = ref()

const { isFetching: loadingWithGetDatabases, data: databaseMsgs } =
  useCustomFetch<IDatabase[]>(`/engine-service/api/v1/database/list`, {
    afterFetch(ctx: AfterFetchContext<IBasic<IDatabase[]>>) {
      if (ctx.data && ctx.data.code === 0) {
        if (databaseId.value === -1) {
          databaseId.value = ctx.data.data[0].id
        }
        return {
          data: ctx.data.data,
          response: ctx.response,
        }
      }
      return {
        data: [],
        response: ctx.response,
      }
    },
  })

/**
 * 重试开关变动
 */
let isRetrySwitchType = ref(!globalConfig.selectedStep.isRetry);
watch(() => globalConfig.selectedStep.isRetry,
  (newValue) => {
    if (newValue) {
      isRetrySwitchType.value = false
    } else {
      isRetrySwitchType.value = true
    }
  },
  { deep: true }
)

</script> 

<template>
  <!-- 主体部分 -->
  <div my-6>
    <Form :model="selectedStep">
      <Form.Item label="用例名称">
        <Input v-model:value="selectedStep.name" placeholder="请输入用例名称" />
      </Form.Item>

      <Row :gutter="27">
        <Col :span="12">
        <Form.Item label="引擎类型">
          <Input v-model:value="selectedStep.engineType" disabled />
        </Form.Item>
        </Col>
        <Col :span="12">
        <Form.Item label="数据库配置">
          <Select v-model:value="selectedStep.databaseId" :loading="loadingWithGetDatabases">
            <Select.Option v-for="{ id, description } in databaseMsgs" :key="id" :value="id">
              <Tooltip :title="description">{{ description }}</Tooltip>
            </Select.Option>
          </Select>
          <!-- <Input v-model:value="selectedStep.databaseId" placeholder="请选择数据库配置" /> -->
        </Form.Item>
        </Col>
      </Row>



      <Form.Item label="SQL文本">
        <Textarea style="height: 300px; width: 100%" v-model:value="selectedStep.sqlText" placeholder="请输入SQL文本" />
      </Form.Item>

      <Row :gutter="30">
        <Col :span="12">
        <Form.Item label="重试类型">
          <Select v-model:value="selectedStep.retryType" :disabled="true" style="width: 100%;">
            <Select.Option value="同步">同步重试</Select.Option>
            <Select.Option value="异步">异步重试</Select.Option>
          </Select>
        </Form.Item>
        </Col>
        <Col :span="12">
        <Form.Item label="首次重试间隔(单位: 秒 )">
          <InputNumber v-model:value="selectedStep.retryFirstInterval" :disabled="isRetrySwitchType"
            style="width: 100%;" />
        </Form.Item>
        </Col>
      </Row>
      <Row :gutter="30">
        <Col :span="12">
        <Form.Item label="重试次数">
          <InputNumber v-model:value="selectedStep.retryCount" :disabled="isRetrySwitchType" style="width: 100%;" />
        </Form.Item>
        </Col>
        <Col :span="12">
        <Form.Item label="失败是否重试(默认关闭)">
          <Switch v-model:checked="selectedStep.isRetry" />
        </Form.Item>
        </Col>
      </Row>

    </Form>

    <RequestConfig ref="requestConfigRef" v-model:body-type="selectedStep.bodyType">
      <template #foot>
        <TabPane key="assertion" tab="断言">
          <EditableTable v-model:data-source-proxy="dataSourceWithAssertion" :custom-fields="['mode', 'action']"
            :columns="columnsWithAssertion" @add-data="
              dataSourceWithAssertion.push({
                ...defaultWithIDatabaseStepAssertion,
              })
              ">
            <template #bodyCell="{ column, isEdit, currentEditableInstance }">
              <template v-if="isEdit && column.key === 'mode'">
                <Select v-model:value="currentEditableInstance[column.key!]">
                  <Select.Option v-for="item in databaseConstantSelectOptions.db_assert_mode" :key="item.id"
                    :value="item.value">
                    <Tooltip :title="item.remark">
                      {{ item.name }}
                    </Tooltip>
                  </Select.Option>
                </Select>
              </template>

              <template v-if="isEdit && column.key === 'action'">
                <Select v-model:value="currentEditableInstance[column.key!]">
                  <Select.Option v-for="item in databaseConstantSelectOptions.db_assert_action" :key="item.id"
                    :value="item.value">
                    <Tooltip :title="item.remark">
                      {{ item.name }}
                    </Tooltip>
                  </Select.Option>
                </Select>
              </template>
            </template>
          </EditableTable>
        </TabPane>
      </template>
    </RequestConfig>
  </div>
</template>
